package com.xaaef.grpc.server.rest;

import com.xaaef.grpc.lib.util.RestResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.HttpStatusCode;
import org.springframework.http.ResponseEntity;
import org.springframework.web.ErrorResponse;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.Instant;

import static com.xaaef.grpc.lib.consts.GlobalConst.HEADER_ERROR_DETAILS;


@Slf4j
@RestControllerAdvice
public class RestGlobalExceptionHandler {


    /**
     * 参数校验统一异常处理
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<Object> handleBindException(MethodArgumentNotValidException e) {
        var fieldError = e.getBindingResult().getFieldError();
        var errorMessage = fieldError != null ? fieldError.getDefaultMessage() : e.getMessage();
        var body = RestResult.result(e.getStatusCode().value(), Instant.now().toEpochMilli(), errorMessage, null);
        return toErrorResponse(e.getStatusCode(), errorMessage, body);
    }


    /**
     * 处理异常
     *
     * @param e
     */
    @ExceptionHandler(value = Exception.class)
    public ResponseEntity<Object> exceptionHandler(Exception e) {
        Object body = null;
        HttpStatusCode statusCode = HttpStatus.INTERNAL_SERVER_ERROR;
        if (e instanceof ErrorResponse er) {
            statusCode = er.getStatusCode();
            body = RestResult.result(
                    er.getStatusCode().value(),
                    Instant.now().toEpochMilli(),
                    e.getMessage(), null
            );
        } else {
            body = RestResult.result(
                    HttpStatus.INTERNAL_SERVER_ERROR.value(),
                    Instant.now().toEpochMilli(),
                    e.getMessage(), null
            );
        }
        return toErrorResponse(statusCode, e.getMessage(), body);
    }


    private static <T> ResponseEntity<T> toErrorResponse(HttpStatusCode statusCode, String error, T body) {
        return ResponseEntity.status(statusCode)
                .header(HEADER_ERROR_DETAILS, URLEncoder.encode(error, StandardCharsets.UTF_8))
                .body(body);
    }


}
